package vip.wangwenhao.autoconfigure.base;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import vip.wangwenhao.common.enums.ResultCode;
import vip.wangwenhao.common.exception.CommonException;
import vip.wangwenhao.common.exception.LimitException;
import vip.wangwenhao.common.result.Result;


/**
 * @author wangwenhao
 */
@RestControllerAdvice
public class GlobalExceptionAdvice {

    private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionAdvice.class);

    /**
     * 400错误 org.springframework.validation.BindException 如：JSR-303验证错误 就会抛出此异常
     * 请求参数校验失败
     *
     * @param e
     * @return
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(BindException.class)
    public Result handleBindException(Exception e) {
        LOGGER.error(ResultCode.REQUEST_PARAM_CHECK_FAILED.getMessage(), e);
        return Result.fail(ResultCode.REQUEST_PARAM_CHECK_FAILED);
    }

    /**
     * 400错误
     * 请求无效
     *
     * @param e
     * @return
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public Result handleHttpRequestNotReadableException(HttpMessageNotReadableException e) {
        LOGGER.error(ResultCode.REQUEST_PARAM_MISS.getMessage() + e);
        return Result.fail(ResultCode.REQUEST_PARAM_MISS, e.getMessage());
    }


    /**
     * 400错误
     * 方法参数验证失败
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler({MethodArgumentNotValidException.class})
    public Result handleValidationException(MethodArgumentNotValidException e) {
        LOGGER.error(ResultCode.METHOD_PARAM_CHECK_FAILED.getMessage() + e);
        return Result.fail(ResultCode.METHOD_PARAM_CHECK_FAILED);
    }

    /**
     * 400 - Bad Request
     * 请求无效
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler({MissingServletRequestParameterException.class})
    public Result missingServletRequestParameterException(MissingServletRequestParameterException e) {
        LOGGER.error(ResultCode.REQUEST_PARAM_CHECK_FAILED.getMessage() + e);
        return Result.fail(ResultCode.REQUEST_PARAM_CHECK_FAILED);
    }

    /**
     * 400 - Bad Request
     * 请求错误
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler({MissingServletRequestPartException.class})
    public Result missingServletRequestPartException(MissingServletRequestPartException e) {
        LOGGER.error(ResultCode.REQUEST_ERROR.getMessage() + e);
        return Result.fail(ResultCode.REQUEST_ERROR);
    }


    /**
     * 400 - Bad Request
     * 方法参数类型不匹配
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler({TypeMismatchException.class})
    public Result typeMismatchException(TypeMismatchException e) {
        LOGGER.error(ResultCode.METHOD_PARAM_NOT_MATCH.getMessage() + e);
        return Result.fail(ResultCode.METHOD_PARAM_NOT_MATCH);
    }


    /**
     * 405 - Method Not Allowed。
     * HttpRequestMethodNotSupportedException是ServletException的子类,需要Servlet API支持
     * 请求方法不支持
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Result handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        LOGGER.error(ResultCode.REQUEST_METHOD_NOT_SUPPORT.getMessage() + e);
        return Result.fail(ResultCode.REQUEST_METHOD_NOT_SUPPORT);
    }

    /**
     * 406
     * 请求内容不可读
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(HttpMediaTypeNotAcceptableException.class)
    public Result httpMediaTypeNotAcceptableException(HttpMediaTypeNotAcceptableException e) {
        LOGGER.error(ResultCode.REQUEST_CONTENT_UNREAD.getMessage() + e);
        return Result.fail(ResultCode.REQUEST_CONTENT_UNREAD);
    }


    /**
     * 415 - Unsupported Media Type。
     * HttpMediaTypeNotSupportedException是ServletException的子类,需要Servlet API支持
     * 响应的内容类型不支持
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler({HttpMediaTypeNotSupportedException.class})
    public Result handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) {
        LOGGER.error(ResultCode.RESPONSE_CONTENT_NOT_SUPPORT.getMessage(), e);
        return Result.fail(ResultCode.RESPONSE_CONTENT_NOT_SUPPORT);
    }

    /**
     * 500错误
     * 请求响应内容错误
     *
     * @param e
     * @return
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(HttpMessageNotWritableException.class)
    public Result httpMessageNotWritableException(HttpMessageNotWritableException e) {
        LOGGER.error(ResultCode.RESPONSE_ERROR.getMessage(), e);
        return Result.fail(ResultCode.RESPONSE_ERROR);
    }

    /**
     * 500错误
     * 服务器内部错误
     *
     * @param e
     * @return
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(CommonException.class)
    public Result handleException(CommonException e) {
        LOGGER.error(e.getResultCode().getMessage(), e);
        return Result.fail(e.getResultCode(), e.getMessage());
    }

    /**
     * 429错误
     * 请求次数限制
     *
     * @param e
     * @return
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(LimitException.class)
    public Result handleException(LimitException e) {
        LOGGER.error(ResultCode.TOO_MANY_REQUESTS.getMessage(), e);
        return Result.fail(ResultCode.TOO_MANY_REQUESTS, e.getMessage());
    }

    /**
     * 429错误
     * 请求次数限制
     *
     * @param e
     * @return
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(IllegalArgumentException.class)
    public Result handleException(IllegalArgumentException e) {
        LOGGER.error(ResultCode.ERROR_SERVER_FAILED.getMessage(), e);
        return Result.fail(ResultCode.ERROR_SERVER_FAILED, e.getMessage());
    }

    /**
     * 403错误
     * 无权限访问
     *
     * @param e
     * @return
     */
    @ResponseStatus(HttpStatus.FORBIDDEN)
    @ExceptionHandler(AccessDeniedException.class)
    public Result handleException(AccessDeniedException e) {
        LOGGER.error(ResultCode.ACCESS_DENIED_EXCEPTION.getMessage(), e);
        return Result.fail(ResultCode.ACCESS_DENIED_EXCEPTION);
    }

    /**
     * 403错误
     * 无权限访问
     *
     * @param e
     * @return
     */
    @ResponseStatus(HttpStatus.FORBIDDEN)
    @ExceptionHandler(InsufficientAuthenticationException.class)
    public Result handleException(InsufficientAuthenticationException e) {
        LOGGER.error(ResultCode.UNAUTHORIZED_REQUEST.getMessage(), e);
        return Result.fail(ResultCode.UNAUTHORIZED_REQUEST);
    }

    /**
     * 500错误
     * 服务器内部错误
     *
     * @param e
     * @return
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(Exception.class)
    public Result handleException(Exception e) {
        LOGGER.error(ResultCode.ERROR_SERVER_FAILED.getMessage(), e);
        return Result.fail(ResultCode.ERROR_SERVER_FAILED, e.getMessage());
    }

}